package com.xqboss.apps.task;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xqboss.apps.domain.order.OrderItem;
import com.xqboss.apps.domain.order.OrderMain;
import com.xqboss.apps.domain.order.PayApply;
import com.xqboss.apps.enums.box.BoxSequenceEnum;
import com.xqboss.apps.enums.order.OrderStatusEnum;
import com.xqboss.apps.enums.order.OrderTypeEnum;
import com.xqboss.apps.enums.order.PayStatusEnum;
import com.xqboss.apps.service.nft.NftNumberService;
import com.xqboss.apps.service.order.OrderItemService;
import com.xqboss.apps.service.order.OrderService;
import com.xqboss.apps.service.order.PayApplyService;
import com.xqboss.apps.service.order.type.impl.BoxOrderTypeExecutor;
import com.xqboss.common.utils.TransactionalManage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 订单定时任务
 * </p>
 *
 * @author Trent
 * @date 2023/9/5
 */
@Component("orderTask")
@Slf4j
public class OrderTask {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private NftNumberService nftNumberService;

    @Autowired
    private PayApplyService payApplyService;

    @Autowired
    private BoxOrderTypeExecutor boxOrderTypeExecutor;

    @Autowired
    private TransactionalManage transactionalManage;

    public void cancelOrder() {
        // 自动取消订单任务
        List<OrderMain> list = orderService.list(new LambdaQueryWrapper<OrderMain>()
                        .select(OrderMain::getId)
                        .eq(OrderMain::getStatus, OrderStatusEnum.UN_PAY)
                        .eq(OrderMain::getException, false)
                        .le(OrderMain::getAutoCancelTime, LocalDateTime.now())
                        .last("LIMIT 100"));
        for (OrderMain orderMain : list) {
            try {
                orderService.close(orderMain.getId());
            } catch (Exception e) {
            }
        }
    }


    /**
     * 异常订单处理
     */
    public void solve(String orderId) {
        try {
            OrderMain orderMain = orderService.getById(Long.parseLong(orderId));
            if (orderMain == null || orderMain.getPayType() != null || orderMain.getPayOrderNo() != null
                    || orderMain.getOrderType() != OrderTypeEnum.Box_NFT || orderMain.getStatus() != OrderStatusEnum.COMPLETED) {
                return;
            }
            OrderItem orderItem = orderItemService.getItemsByOrderMain(orderMain.getId()).get(0);

            PayApply payApply = payApplyService.getOne(new LambdaQueryWrapper<PayApply>()
                    .eq(PayApply::getOrderMainId, orderId)
                    .eq(PayApply::getPayStatus, PayStatusEnum.TRADE_SUCCESS)
            );
            transactionalManage.executeWithException(() -> {
                nftNumberService.distributeNftNumber(216L, orderItem, 1, true);
                // 更新支付信息
                orderService.update(new LambdaUpdateWrapper<OrderMain>()
                        .set(OrderMain::getPayType, payApply.getPayType())
                        .set(OrderMain::getActualPaymentAmount, payApply.getPayAmount())
                        .set(OrderMain::getPayOrderNo, payApply.getId())
                        .set(OrderMain::getPayAccount, payApply.getBuyerAccount())
                        .eq(OrderMain::getId, payApply.getOrderMainId()));
                payApplyService.update(new LambdaUpdateWrapper<PayApply>()
                        .eq(PayApply::getId, payApply.getId())
                        .set(PayApply::getIsOrderHandler, true));
                return true;
            });
        } catch (Exception e) {
            log.error("订单状态处理异常:" + orderId, e);
            // 标记订单异常
            orderService.exception(Long.valueOf(orderId));
        }
    }

    /**
     * 异常订单处理
     */
    public void solve1(String orderIds) {
        String[] orderIdArr = orderIds.split(",");
        for (String orderId : orderIdArr) {
            try {
                OrderMain orderMain = orderService.getById(Long.parseLong(orderId));
                if (orderMain == null || orderMain.getPayType() != null || orderMain.getPayOrderNo() != null
                        || orderMain.getOrderType() != OrderTypeEnum.Box_NFT || orderMain.getStatus() != OrderStatusEnum.PAYED) {
                    return;
                }
                PayApply payApply = payApplyService.getOne(new LambdaQueryWrapper<PayApply>()
                        .eq(PayApply::getOrderMainId, orderId));
                boxOrderTypeExecutor.orderPayedPost(orderMain);
                // 更新支付信息
                orderService.update(new LambdaUpdateWrapper<OrderMain>()
                        .set(OrderMain::getPayType, payApply.getPayType())
                        .set(OrderMain::getActualPaymentAmount, payApply.getPayAmount())
                        .set(OrderMain::getPayOrderNo, payApply.getId())
                        .set(OrderMain::getPayAccount, payApply.getBuyerAccount())
                        .eq(OrderMain::getId, payApply.getOrderMainId()));
                payApplyService.update(new LambdaUpdateWrapper<PayApply>()
                        .eq(PayApply::getId, payApply.getId())
                        .set(PayApply::getIsOrderHandler, true));
            } catch (Exception e) {
                log.error("订单状态处理异常:" + orderId, e);
                // 标记订单异常
                orderService.exception(Long.valueOf(orderId));
            }
        }
    }

    public void solveAll() {
        List<OrderMain> list = orderService.lambdaQuery()
                .select(OrderMain::getId)
                .eq(OrderMain::getException, true)
                .eq(OrderMain::getOrderType , OrderTypeEnum.Box_NFT)
                .eq(OrderMain::getStatus, OrderStatusEnum.COMPLETED)
                .gt(OrderMain::getCreateTime, DateUtil.beginOfDay(new Date()))
                .list();
        if (!list.isEmpty()) {
            for (OrderMain t : list) {
                solve(t.getId().toString());
            }
        }

    }
}
